package org.sam.beatles.utils;

import java.lang.reflect.Field;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;

/**
 * spring工具助手
 * @author sam
 *
 */
public class SpringBeanUtil implements BeanUtil {

	/**
	 * 注入的spring上下文对象
	 */
	private ApplicationContext spring;

	/**
	 * 注入的spring上下文对象
	 * 
	 * @return
	 */
	public ApplicationContext getSpring() {
		return spring;
	}

	/**
	 * 注入的spring上下文对象
	 * 
	 * @param spring
	 */
	@Autowired
	public void setSpring(ApplicationContext spring) {
		this.spring = spring;
	}

	/**
	 * 根据实体名称获取bean的实例
	 * 
	 * @param <T>
	 * @param entityName
	 * @return
	 */
	@Override
	@SuppressWarnings("unchecked")
	public <T> T getBean(String entityName) {
		if (StringUtils.isEmpty(entityName))
			return null;

		try {
			String beanName = getBeanName(entityName);
			if (spring.containsBean(beanName))
				return (T) spring.getBean(beanName);
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 动态注册bean到系统里
	 * 
	 * @param name 自定义名称
	 * @param bean 被注册对象
	 * @return
	 */
	@Override
	public boolean registerBean(String name, Object bean) {
		if (StringUtils.isEmpty(name))
			return false;

		if (bean == null)
			return false;

		try {
			DefaultListableBeanFactory factory = (DefaultListableBeanFactory) spring.getAutowireCapableBeanFactory();
			BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(bean.getClass());
			factory.registerBeanDefinition(name, builder.getBeanDefinition());
			return true;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 根据class名称获取bean名称
	 * 
	 * @param clsName
	 *            class名称
	 * @return 首字母小写
	 */
	public static String getBeanName(String clsName) {
		if (StringUtils.isEmpty(clsName)) {
			return "";
		}
		if (StringUtils.isAllUpperCase(clsName.substring(1,2))){
			return clsName;
		}
		return clsName.substring(0, 1).toLowerCase() + clsName.substring(1);
	}

	/**
	 * 动态注册bean到系统里 使用首字母小写的方式
	 * 
	 * @param bean 被注册对象
	 * @return
	 */
	@Override
	public boolean registerBean(Object bean) {
		if (bean == null)
			return false;

		String beanName = getBeanName(bean.getClass().getSimpleName());
		return registerBean(beanName, bean);
	}

	/**
	 * 通过名称取消bean注册
	 * 
	 * @param name bean名称
	 * @return
	 */
	@Override
	public boolean removeBean(String name) {
		if (StringUtils.isEmpty(name))
			return false;

		try {
			DefaultListableBeanFactory factory = (DefaultListableBeanFactory) spring.getAutowireCapableBeanFactory();
			factory.removeBeanDefinition(name);
			return true;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return false;
	}

	/**
	 * 通过bean对象取消bean注册
	 * 
	 * @param bean
	 * @return
	 */
	@Override
	public boolean removeBean(Object bean) {
		if (bean == null)
			return false;

		String beanName = getBeanName(bean.getClass().getSimpleName());
		return removeBean(beanName);
	}
	
	/**
	 * 通过getbeans的方式自动注入dao
	 */
	@Override
	public void scanForAutoWired(Object obj) {
		try {
			Class<?> entityCls = obj.getClass();

			while (!Object.class.equals(entityCls)) {

				Field[] fields = entityCls.getDeclaredFields();
				for (Field field : fields) {
					Autowired[] annotationsByType = field.getAnnotationsByType(Autowired.class);
					if (annotationsByType != null && annotationsByType.length > 0) {
						String name = field.getType().getSimpleName();
						field.setAccessible(true);
						String bigName = name + "Impl";
						String shortName = name.substring(0, 1).toLowerCase() + name.substring(1) + "Impl";

						if (spring.containsBean(bigName)) {
							field.set(obj,spring.getBean(bigName));
						} else if (spring.containsBean(shortName)) {
							field.set(obj, spring.getBean(shortName));
						} else {
							Class<?> cls = field.getType();
							field.set(obj, spring.getBean(cls));
						}
					}
				}
				entityCls = entityCls.getSuperclass();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * 发布事件
	 * @param event
	 */
	@Override
	public void publishEvent(ApplicationEvent event) {
		this.spring.publishEvent(event);
	}
}
